//
// Created by yanhai on 2020/2/28.
//

#pragma once

#include <boost/filesystem.hpp>

namespace muh {
namespace os {
namespace path {

/**
 * 传入一个路径，判断其是否存在
 * @param path 路径
 * @return 存在返回true，否则返回false
 */
inline bool exists(const std::string &path) noexcept
{
    return boost::filesystem::exists(path);
}

/**
 * 传入一个路径，判断其是否为文件
 * @param path 路径
 * @return 存在并且是文件返回true，否则返回false
 */
inline bool isfile(const std::string &path) noexcept
{
    return boost::filesystem::is_regular_file(path);
}

/**
 * 传入一个路径，判断其是否为目录
 * @param path 路径
 * @return 存在并且是目录返回true，否则返回false
 */
inline bool isdir(const std::string &path) noexcept
{
    return boost::filesystem::is_directory(path);
}

/**
 * 获取文件的大小
 * 如果文件不存在，则抛出 boost::filesystem::filesystem_error 异常
 * @param filename 文件名
 * @return 文件大小
 */
inline boost::uintmax_t getsize(const std::string &filename)
{
    return boost::filesystem::file_size(filename);
}

/**
 * 获取文件或者目录的最后修改时间（比如改变文件内容）
 * 如果路径不存在，则抛出 boost::filesystem::filesystem_error 异常
 * @param filename 路径
 * @return 时间戳
 */
inline std::time_t getmtime(const std::string &filename)
{
    return boost::filesystem::last_write_time(filename);
}

/**
 * 获取文件或者目录的最后访问（读取）时间（比如通过touch修改）
 * 如果路径不存在，则抛出 boost::filesystem::filesystem_error 异常
 * @param filename 路径
 * @return 时间戳
 */
inline std::time_t getatime(const std::string &filename)
{
    // todo ...
    return 0;
}

/**
 * 获取文件或者目录的最后元数据修改时间（比如改变权限或所有权等属性）
 * 如果路径不存在，则抛出 boost::filesystem::filesystem_error 异常
 * @param filename 路径
 * @return 时间戳
 */
inline std::time_t getctime(const std::string &filename)
{
    // todo ...
    return 0;
}

/**
 * 给定一个路径名列表，返回最长的相同前缀
 * >>> ["/var/log/test1", "/var/log/test2"]
 * "/var/log/test"
 * >>> ["/var/log/test1", "/tmp/test1"]
 * "/"
 * @param _first 容器迭代器开始位置
 * @param _last 容器迭代器结束位置
 * @return 最长的相同前缀
 */
template<typename _ForwardIterator>
inline std::string commonprefix(_ForwardIterator _first, _ForwardIterator _last)
{
    auto _pair = std::minmax_element(_first, _last);
    std::string min = *_pair.first;
    std::string max = *_pair.second;
    for (std::string::size_type i = 0; i < min.length(); i++) {
        if (min[i] != max[i]) {
            return min.substr(0, i);
        }
    }
    return min;
}


}
}
}
